﻿using MiniFox.Exceptions;
using MiniFox.Resources;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MiniFox.Scripting
{
    /// <summary>
    /// 
    /// </summary>
    public abstract class FunctionBase
    {
        string _name;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="functionSetting"></param>
        protected internal FunctionBase(IFunctionSetting functionSetting)
        {
            this._name = functionSetting.Name;
            this.Arguments = new Dictionary<string, Type>();
            this.Description = functionSetting.Description;
            this.ReturnFormat = functionSetting.ReturnFormat;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        public FunctionBase(string name)
        {
            _name = name;
            this.Arguments = new Dictionary<string, Type>();
        }
        /// <summary>
        /// 
        /// </summary>
        public string Name
        {
            get { return _name; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string ReturnFormat
        {
            get;
            set;
        }
        /// <summary>
        /// 
        /// </summary>
        public string Description
        {
            get;
            set;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="arguments"></param>
        /// <returns></returns>
        public virtual object Execute(params object[] arguments)
        {
            if (arguments.Length != this.Arguments.Count)
                throw new InvalidOperationException(CommonMessages.MSG_InvalidArgument);

            Dictionary<string, object> parameters = new Dictionary<string, object>();
            //初始化参数列表
            var i = 0;
            foreach (var argument in this.Arguments)
            {
                try
                {
                    object val = Convert.ChangeType(arguments[i++], argument.Value);
                    parameters.Add(argument.Key, val);
                }
                catch
                {

                    throw new InvalidParameterException(argument.Key, string.Format(CommonMessages.MSG_CommonTypeUnmatched, argument.Key, argument.Value));
                }
            }
            //调用
            object returnVal = Execute(parameters);
            if (string.IsNullOrWhiteSpace(this.ReturnFormat))
                return returnVal;
            else
                return string.Format(this.ReturnFormat, returnVal);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="arguments"></param>
        /// <returns></returns>
        protected abstract object Execute(IDictionary<string, object> arguments);
        /// <summary>
        /// 
        /// </summary>
        internal IDictionary<string, Type> Arguments
        {
            get;
        }
    }
}
